import { defineStore } from 'pinia'
import { saveAnswerToServer, saveBatchAnswers, recordViolation } from '@/api/student/exam'
import { ref, computed, reactive, watch } from 'vue'
const STORAGE_KEY = 'exam-store'
/**
 * 考试状态管理
 * 管理学生考试过程中的各种状态，包括：
 * - 当前考试信息
 * - 学生答案
 * - 答题时间
 * - 违规记录
 * - 全屏状态
 */
export const useExamStore = defineStore('exam', () => {
    // 状态 (state)
    const currentExam = ref(null) // 当前考试信息
    const answers = ref({}) // 学生答案集合，key为paperDetailId，value为答案对象{answer, updateTime}
    const timeSpent = ref({}) // 每道题花费的时间，key为paperDetailId，value为时间(秒)
    const violationCount = ref(0) // 违规次数统计
    const remainingTime = ref(0) // 剩余考试时间(秒)
    const lastSyncTime = ref(null) // 最后一次同步答案的时间戳
    const isFullscreen = ref(false) // 是否全屏状态
    const currentQuestionId = ref(null) // 当前查看的题目ID (实际上是paperDetailId)
    const switchScreenCount = ref(0) // 切屏次数统计
    const allowCopyPaste = ref(true) // 是否允许复制粘贴
    const questionNavStatus = ref({}) // 题目导航状态，0:未答 1:已答 2:标记

    // 计算属性 (getters)
    const answeredCount = computed(() => Object.keys(answers.value).length) // 已答题数量

    // 监控 answers的变化
    // watch(answers, (oldVal,newVal) => {
    //     if (typeof answers.value !== 'object') {
    //         console.log('类型发生转化111', answers.value)
    //         console.log('类型发生转化旧', oldVal)
    //         console.log('类型发生转化', newVal)
    //         console.log(typeof answers.value)
    //     }
    // }, { immediate: true }) // immediate: true 表示初始化时立即执行一次

    /**
     * 检查是否有未同步的答案
     * @returns {boolean} 如果有答案未同步则返回true
     */
    const hasUnsyncedAnswers = computed(() => {
        if (!lastSyncTime.value) return false
        return Object.values(answers.value).some(
            answer => answer.updateTime > lastSyncTime.value
        )
    })

    /**
     * 获取所有题目ID
     * @returns {Array} 当前考试所有题目的paperDetailId数组
     */
    const allQuestionIds = computed(() => {
        if (!currentExam.value) return []
        return currentExam.value.bigQuestions.flatMap(
            bq => bq.questions.map(q => q.paperDetailId)
        )
    })

    /**
     * 获取未答题ID列表
     * @returns {Array} 未答题的paperDetailId数组
     */
    const unansweredQuestionIds = computed(() => {
        return allQuestionIds.value.filter(id => {
            // console.log('answers 类型：' + answers.value.constructor.name)
            // console.log(answers.value)

            const answerObj = answers.value[id]

            // 先检查答案对象是否存在
            if (!answerObj) return true

            // 再检查答案内容有效性（兼容多类型场景）
            return [null, ""].includes(answerObj.answer)        // 空值/空字符串
                || (Array.isArray(answerObj.answer) && answerObj.answer.length === 0) // 空数组
                || (typeof answerObj.answer === "object" && Object.keys(answerObj.answer).length === 0) // 空对象
        })
    })

    /**
     * 获取指定题目的答案内容
     * @param {string} paperDetailId 试卷详情ID
     * @returns {string} 该题目的答案内容
     */
    const getAnswerContent = (paperDetailId) => {
        return answers.value[paperDetailId]?.answer || ''
    }

    // 方法 (actions)
    /**
     * 设置当前考试信息并初始化相关状态
     * @param {Object} exam 考试信息对象
     */
    function setCurrentExam(exam) {
        
        currentExam.value = exam
        remainingTime.value = exam.duration

        answers.value = {}
        timeSpent.value = {}
        violationCount.value = 0
        lastSyncTime.value = null
        currentQuestionId.value = exam.bigQuestions[0]?.questions[0]?.paperDetailId || null
        switchScreenCount.value = 0

        // 初始化题目导航状态
        questionNavStatus.value = {}
        if (exam.bigQuestions) {
            exam.bigQuestions.forEach(bq => {
                bq.questions.forEach(q => {
                    questionNavStatus.value[q.paperDetailId] = 0 // 0: 未答
                })
            })
        }
    }

    /**
     * 保存单个题目答案
     * @param {number} paperDetailId 试卷详情ID
     * @param {string} answer 答案内容
     * @param {number} questionId 题目ID
     */
    async function saveAnswer(paperDetailId, answer, questionId) {
        const now = Date.now()
        answers.value[paperDetailId] = {
            answer,
            updateTime: now
        }

        // 更新题目导航状态为已答
        questionNavStatus.value[paperDetailId] = 1

        try {
            await saveAnswerToServer(currentExam.value.id, {
                paperDetailId: paperDetailId,
                questionId: questionId,
                answer,
                timeSpent: timeSpent.value[paperDetailId] || 0
            })
            // 同步未更新，确保失联期间答案已同步
            syncAnswers()
            lastSyncTime.value = now
        } catch (error) {
            console.error('保存答案失败:', error)
        }
    }

    /**
     * 同步所有未保存的答案到服务器
     */
    async function syncAnswers() {
        if (!hasUnsyncedAnswers.value || !currentExam.value) return

        // if (!isOnline.value) {
        //     console.log('网络未连接，无法同步答案')
        //     return
        // }

        // paperDetailId -> q.id
        const questionIdMap = {}
        if (currentExam.value.bigQuestions) {
            currentExam.value.bigQuestions.forEach(bq => {
                bq.questions.forEach(q => {
                    questionIdMap[q.paperDetailId] = q.id
                })
            })
        }

        // 过滤出需要同步的答案并格式化数据结构
        const answersToSync = Object.entries(answers.value)
            .filter(([, { updateTime }]) => updateTime > (lastSyncTime.value || 0))
            .map(([paperDetailId, { answer }]) => ({
                paperDetailId: parseInt(paperDetailId),
                questionId: questionIdMap[parseInt(paperDetailId)],
                answer,
                timeSpent: timeSpent.value[paperDetailId] || 0
            }))

        if (answersToSync.length === 0) return

        // TODO:修改id,examId
        try {
            await saveBatchAnswers(currentExam.value.id, { answers: answersToSync })
            lastSyncTime.value = Date.now()
        } catch (error) {
            console.error('同步答案失败:', error)
        }
    }

    /**
     * 更新题目答题时间
     * @param {number} paperDetailId 试卷详情ID
     * @param {number} time 花费时间(秒)
     */
    function updateTimeSpent(paperDetailId, time) {
        timeSpent.value[paperDetailId] = time
    }

    /**
     * 记录违规行为
     * @param {string} type 违规类型
     * @param {string} details 违规详情
     * @returns {Promise<boolean>} 是否强制交卷
     */
    async function recordViolationFunc(type, details = '') {
        violationCount.value++

        // 如果是切屏违规，记录切屏次数
        if (type === 'switchScreen') {
            switchScreenCount.value++
        }

        try {
            const { data } = await recordViolation(currentExam.value.id, {
                type,
                timestamp: new Date().toISOString(),
                details
            })

            return data.shouldForceSubmit
        } catch (error) {
            console.error('记录违规失败:', error)
            return false
        }
    }

    /**
     * 更新剩余考试时间
     * @param {number} time 剩余时间(秒)
     * Timer来设置
     */
    function updateRemainingTime(time) {
        remainingTime.value = time
    }

    /**
     * 设置全屏状态
     * @param {boolean} value 是否全屏
     */
    function setFullscreen(value) {
        isFullscreen.value = value
    }

    /**
     * 设置当前查看的题目
     * @param {number} paperDetailId 试卷详情ID
     */
    function setCurrentQuestion(paperDetailId) {
        currentQuestionId.value = paperDetailId
    }

    /**
     * 标记/取消标记题目
     * @param {number} paperDetailId 试卷详情ID
     * @param {boolean} marked 是否标记
     */
    function markQuestion(paperDetailId, marked = true) {
        // 如果已答题，在已答(1)和标记(2)之间切换
        // 如果未答题，在未答(0)和标记(2)之间切换
        const currentStatus = questionNavStatus.value[paperDetailId] || 0

        if (marked) {
            questionNavStatus.value[paperDetailId] = 2 // 标记
        } else if (currentStatus === 2) {
            // 取消标记，恢复为已答或未答状态
            questionNavStatus.value[paperDetailId] = answers.value[paperDetailId] ? 1 : 0
        }
    }

    /**
     * 初始化已保存的答案(从服务器加载),存pinia
     * @param {Array} savedAnswers 已保存的答案数组
     */
    function initSavedAnswers(savedAnswers) {
        if (!Array.isArray(savedAnswers)) return

        // console.log(savedAnswers)  // 对象数组，所有答案均被格式化字符串

        const now = Date.now()
        savedAnswers.forEach(item => {
            answers.value[item.paperDetailId] = {
                answer: item.answer,
                updateTime: now - 1000 // 设置为稍早的时间，避免再次同步（该字段仅用于前端）
            }

            timeSpent.value[item.paperDetailId] = item.timeSpent

            // 更新导航状态为已答
            if (item.answer != null && item.answer.trim() !== '') {
                questionNavStatus.value[item.paperDetailId] = 1 // 标记为已答
            } else {
                questionNavStatus.value[item.paperDetailId] = 0 // 标记为未答
            }
        })

        lastSyncTime.value = now
    }

    /**
     * 重置考试状态
     */
    function reset() {
        currentExam.value = null
        answers.value = {}
        timeSpent.value = {}
        violationCount.value = 0
        remainingTime.value = 0
        lastSyncTime.value = null
        isFullscreen.value = false
        currentQuestionId.value = null
        switchScreenCount.value = 0
        questionNavStatus.value = {}
    }

    function clearAllExamData() {
        reset()
        // 1. 清除 Pinia 的持久化存储
        localStorage.removeItem(STORAGE_KEY)
    }

    return {
        // 状态
        currentExam,
        answers,
        timeSpent,
        violationCount,
        remainingTime,
        lastSyncTime,
        isFullscreen,
        currentQuestionId,
        switchScreenCount,
        allowCopyPaste,
        questionNavStatus,

        // 计算属性
        answeredCount,
        hasUnsyncedAnswers,
        allQuestionIds,
        unansweredQuestionIds,


        // 方法
        getAnswerContent,
        setCurrentExam,
        saveAnswer,
        syncAnswers,
        updateTimeSpent,
        recordViolation: recordViolationFunc,
        updateRemainingTime,
        setFullscreen,
        setCurrentQuestion,
        markQuestion,
        initSavedAnswers,
        reset,
        clearAllExamData
    }
}, {
    // 持久化存储
    persist: {
        key: STORAGE_KEY,
        storage: localStorage,
    }
})